﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using HA.ModFlow.Domain.DomainLayer;

using HA.MT3DMS.FileLayer;

using System.Runtime.Serialization.Formatters.Binary;

using System.Runtime.Serialization;

using HA.ModFlow.Infrastructure;


namespace HA.MT3DMS.DomainLayer
{

    /// <summary>
    /// 设计用于中间层数据的保存
    /// </summary>
    [Serializable]
    public class MT3DMSData
    {

        public MT3DMSData(ModFlowData mf)
        {


            //利用modflow的一些基础设置，来初始化自身的设置

            this._mfData = mf;





            _basicTransport = new BasicTransport(_mfData.ModelOption.Units);






            this._advection = new Advection();

            this._chemicalReaction = new ChemicalReaction();

            this._dispersion = new Dispersion();

            this._sourceSinkMixing = new SourceSinkMixing();
            this._Gcgolver = new GCGSolver();



            //初始化对应的设置


            this.ReserveInnerEvents();



            this.ReadModflowSetup();





 
        }

        ModFlowData _mfData;

        /// <summary>
        /// 所依附的modflow数据
        /// </summary>
        public ModFlowData MfData
        {
            get { return _mfData; }
            
        }




        BasicTransport _basicTransport;

        public BasicTransport BasicTransport
        {
            get { return _basicTransport; }
            set { _basicTransport = value; }
        }


        Advection _advection;

        public Advection Advection
        {
            get { return _advection; }
            set { _advection = value; }
        }

        ChemicalReaction _chemicalReaction;

        public ChemicalReaction ChemicalReaction
        {
            get { return _chemicalReaction; }
            set { _chemicalReaction = value; }
        }

        Dispersion _dispersion;

        public Dispersion Dispersion
        {
            get { return _dispersion; }
            set { _dispersion = value; }
        }

        SourceSinkMixing _sourceSinkMixing;

        public SourceSinkMixing SourceSinkMixing
        {
            get { return _sourceSinkMixing; }
            set { _sourceSinkMixing = value; }
        }

        GCGSolver _Gcgolver;

        public GCGSolver Gcgolver
        {
            get { return _Gcgolver; }
            set { _Gcgolver = value; }
        }

        #region 受保护的函数



        protected void ReserveInnerEvents()
        {


            this._basicTransport.Grid.GridReseted += new EventHandler(Grid_GridReseted);


           
            
            this._basicTransport.SpeciesCollecion.SpecifiesChanged += new EventHandler(SpeciesCollecion_SpecifiesChanged);

            this._basicTransport.StressPeriod.StressPeriodChanged += new EventHandler(StressPeriod_StressPeriodChanged);




        }

        void StressPeriod_StressPeriodChanged(object sender, EventArgs e)
        {
            MTStressPeriodCollecion col = sender as MTStressPeriodCollecion;

            this._sourceSinkMixing.OnStressPeriodReset(col.Periods.Count);


            
        }

        void SpeciesCollecion_SpecifiesChanged(object sender, EventArgs e)
        {
            MTSpeciesCollecion col = sender as MTSpeciesCollecion;


            List<string> names = new List<string>();
            foreach (MTSpecies item in col.Species)
            {

                names.Add(item.Name);

                

            }


            this._sourceSinkMixing.OnSpeciesReset(names);

            this._chemicalReaction.OnSpeciesReset(names);

        }



        protected void ReadModflowSetup()
        {

          

            this._basicTransport.ReadModflowSetup(this._mfData);

            this._sourceSinkMixing.ResetModflow(this._mfData);

 

        }

        void Grid_GridReseted(object sender, EventArgs e)
        {
            MTGrid grid = sender as MTGrid;

            this._dispersion.OnGridReset(grid.Nrows,grid.Ncols,grid.Nlayers);

            this._chemicalReaction.OnGridReset(grid.Nrows, grid.Ncols, grid.Nlayers);

            this._sourceSinkMixing.OnGridReset(grid.Nrows, grid.Ncols, grid.Nlayers);


        }


        #endregion



        public void ResetModflowSetup(ModFlowData modflow)
        {
            this._mfData = modflow;

            this.ReadModflowSetup();

        }

        /// <summary>
        /// 输出各种文件  包括生成后处理配置文件
        /// </summary>
        /// <param name="path"></param>
        public void WriteFiles(string path)
        {

            #region

            MT3DMSFiles files = new MT3DMSFiles();


            //基础包

            BasicTransportPack basic = this._basicTransport.ToPack();

            //更新一些标记

            if (this._advection.Enabled)
            {
                basic.ADV = "T";

                //其他选项包

                AdvectionPack ad = this._advection.ToPack();

                files.Packages.Add(ad);
                
                
            }

            if (this._dispersion.Enabled)
            {
                basic.DSP = "T";

                DispersionPack ds = this._dispersion.ToPack();

                files.Packages.Add(ds);
                
            }


            if (this._sourceSinkMixing.Enabled)
            {

                SSMixingPack pack = this._sourceSinkMixing.ToPack();

                files.Packages.Add(pack);

                basic.SSM = "T";
                
            }


            if (this._chemicalReaction.Enabled)
            {

                ChemicalReactionPack pack = this._chemicalReaction.ToPack();

                files.Packages.Add(pack);

                basic.RCT = "T";
                
            }




            basic.GCG = "T";


            files.BasicPack = basic;








            //解法包

            GCGSolverPack gcg = this._Gcgolver.ToPack();
            files.GcgPack = gcg;



       

       





            files.WriteFiles(path);


            #endregion


            //开始输出后处理配置文件


            #region

            List<PmStressPeriod> spConfig = new List<PmStressPeriod>();

            List<int> timeSteps = new List<int>();

            List<int> tranSteps = new List<int>();

            


            foreach (MTStressPeriod item in this.BasicTransport.StressPeriod.Periods)
            {
                double tss = 0;

                if (this._basicTransport.OutputControl.StepsType==TimeStepType.SpecifiedTimes)
                {
                    //timeSteps.AddRange(this._basicTransport.OutputControl.Timesteps);
                    
                }


                if (this._basicTransport.OutputControl.StepsType == TimeStepType.SpecifiedTimes)
                {

                }

                if (this._basicTransport.OutputControl.StepsType==TimeStepType.EndSimulation)
                {
                    

                }


                if (item.TransStepSize!=0)
                {
                    tss = item.TransStepSize;
                    
                }






                



            }


         


            #endregion






        }

        public void DeleteMT3DFiles(string path)
        {

            int speciesNumber = this.BasicTransport.SpeciesCollecion.Species.Count;//污染物数量


            MT3DMSFiles.DeleteMT3DFiles(path, speciesNumber);




        
        }



        [NonSerialized ]
        MT3DOutputResult _mt3dOutputFileResult;
        /// <summary>
        /// 存放所有污染物输出的所有的文件数据信息
        /// </summary>
        public MT3DOutputResult Mt3dOutputFileResult
        {
            get { return _mt3dOutputFileResult; }
            //set { _mt3dOutputFileResult = value; }
        }




        /// <summary>
        /// 读取结果文件
        /// 参数路径为文件夹的路径：例如 C:\Documents and Settings\Administrator\桌面\mt3d01\solutions
        /// </summary>
        /// <param name="path"></param>
        public void ReadOutputResult(string path)
        {

            //读取MT3D结果文件  


            this.ReadMT3DUcnBinaryFile(path);




            #region  //伪代码  测试计算Mass

           


            //double[] xLength = this.MfData.GridData.ColCoords;
            //double[] yLength = this.MfData.GridData.RowCoords;
            //List<double[,]> zLength = this.MfData.GridData.Elevations;//zLength中的值从上到下存放中心高程   xLength和yLength分别按坐标从小到大存放单元格距离（存放坐标不合适，应为可能旋转平移了）
           

            //CellCenterDataSet3d _cellCenterHeadDataSet = this.MfData.MfResult.CellCenterDataSet3d[0];


            //List<double[,]> porosity = this.ChemicalReaction.Porosity2;

            //for (int layer = 0; layer < porosity.Count; layer++)
            //{
            //    for (int row = 0; row < porosity[layer].GetLength(0); row++)
            //    {
            //        for (int col = 0; col < porosity[layer].GetLength(1); col++)
            //        {
            //            porosity[layer][row, col] = 0.3;
            //        }
            //    }
            //}

            //CellCenterDataSet3d _currentSpeciesDataSet = this.Mt3dOutputFileResult.AllSpeciesMT3DResultList[0].SpeciesOutputFileResult[0].CellCenterGridValue ;

            //double calMin = 0;

            //double calMax = 0;


            //calMin = _currentSpeciesDataSet.MinValue;

            //calMax = _currentSpeciesDataSet.MaxValue;
               

            //double factory = 1.0;

            //List<int[]> ijk = new List<int[]>();

            //for (int row = 0; row < 20; row++)
            //{
            //    for (int col = 0; col < 16; col++)
            //    {
            //        int[] cellIjk = new int[3];
            //        cellIjk[0] = row;
            //        cellIjk[1] = col;
            //        cellIjk[2] = 0;

            //        ijk.Add(cellIjk);
            //    }

            //}

            //double result;
            //result = ComputeMass.Compute(
            //    xLength, yLength, zLength,
              
            // porosity,

            //    calMin,
            //    calMax,

            //    _cellCenterHeadDataSet,
               
               
            //    _currentSpeciesDataSet,


            //    factory,

            // ijk
            //    );

            #endregion



        }


         #region 内部方法


        /// <summary>
        /// 读取mt3d的二进制结果文件  例如：mt3d001.ucn 
        /// </summary>
        /// <param name="path"></param>
        private void ReadMT3DUcnBinaryFile(string path)
        {
            #region 读取二进制文件的方法

            //首先计算所有的污染的个数

            int speciesNum = this.BasicTransport.SpeciesCollecion.SpeciesCount;

            try
            {

                //创建结果文件的数据存储对象
                this._mt3dOutputFileResult = new MT3DOutputResult(speciesNum);


                //然后计算每个污染物输出的文件的个数

                for (int i = 0; i < this.BasicTransport.SpeciesCollecion.Species.Count; i++)
                {
                    //遍历污染物信息集合


                    //二进制文件的路径  C:\Documents and Settings\Administrator\桌面\mt3d01\solutions\MT3D001.UCN

                    string outputFilePath = path + FileNameConfigHelper.GetInputFileName(i);


                    MT3DSpeciesResult mt3dSpeciesResult = new MT3DSpeciesResult();

                    mt3dSpeciesResult.SpecieName = this.BasicTransport.SpeciesCollecion.Species[i].Name;//污染物名称


                    //取得每个污染物输出多少文件  以及每个文件的字节数
                    long partLength = 0;//每个文件字节数
                    //int fileNum;//文件个数

                    UcnFileReader.GetUcnNum(outputFilePath, ref partLength);
                    //mt3dSpeciesResult.OutputFileNum = fileNum;

                    //遍历该污染物生成的所有文件 读取文件内容

                    #region

                    if (partLength > 0)
                    {

                        //读取二进制文件中所有的数据
                        List<UcnData> ucnDataResult = UcnFileReader.ReadUcnFile(outputFilePath);





                        if (ucnDataResult != null)
                        {

                            for (int index = 0; index < ucnDataResult.Count; index++)
                            {

                                OutputFileData fileValue = new OutputFileData();


                                fileValue.FileLabel = (index + 1).ToString();//文件标签  非必要信息

                                fileValue.StressStep = ucnDataResult[index].KPER;//应力期
                                fileValue.TimeStep = ucnDataResult[index].KSTP;//时间步长
                                fileValue.TransStep = ucnDataResult[index].NTRANS;//传输步长

                                fileValue.Time = ucnDataResult[index].TOTIM;//逝去时间
                                fileValue.Conc = ucnDataResult[index].TEXT.ToString();//浓度标志字符串

                                fileValue.Col = ucnDataResult[index].NCOL;//网格单元列数
                                fileValue.Row = ucnDataResult[index].NROW;//网格单元行数
                                fileValue.Layer = ucnDataResult[index].ILAY;//网格单元层数

                                //因为上述读取二进制 UCN 文件的方法返回的数据存储形式和主程序（double[row,col,layer]）的顺序不同  故需要转换

                                float[, ,] ucnData = ucnDataResult[index].values;//三维数组的存放顺序是 float [ layer , row  , col  ] 

                                //要传递给CellCenterDataSet3d  存放顺序应该是 double[ rows  ,  cols  , layers  ] 
                                double[, ,] concValue = new double[ucnData.GetLength(1), ucnData.GetLength(2), ucnData.GetLength(0)];

                                for (int layer = 0; layer < ucnData.GetLength(0); layer++)
                                {
                                    for (int row = 0; row < ucnData.GetLength(1); row++)
                                    {
                                        for (int col = 0; col < ucnData.GetLength(2); col++)
                                        {
                                            concValue[row, col, layer] = ucnData[layer, row, col];
                                        }
                                    }

                                }


                                CellCenterDataSet3d dataResult = null;

                                //if (this._mfData != null)
                                //{
                                //    dataResult = new CellCenterDataSet3d(concValue, this._mfData.GridData.WaterGrid.GetIBounds(),this._basicTransport .CINACT );
                                //}
                                //else
                                //{
                                //    dataResult = new CellCenterDataSet3d(concValue, null, this._basicTransport.CINACT);
                                //}

                                List<int[,]> icbund = null;
                                if (this.BasicTransport != null)
                                {
                                    if (this.BasicTransport.Grid != null)
                                    {
                                        icbund = this.BasicTransport.Grid.GetICBUND();
                                    }                                    
                                }
                                if (icbund !=null )
                                {
                                    if (icbund .Count <=0)
                                    {
                                        icbund = null;
                                    }
                                }
                                dataResult = new CellCenterDataSet3d(concValue, icbund, this._basicTransport.CINACT);



                                fileValue.CellCenterGridValue = dataResult;


                                //标签
                                fileValue.CellCenterGridValue.Label = fileValue.StressStep + "_" + fileValue.TimeStep + "_" + fileValue.TransStep + "_" + fileValue.Time.ToString();


                                //逝去时间
                                fileValue.CellCenterGridValue.EllapseTime = ucnDataResult[index].TOTIM;



                                mt3dSpeciesResult.AddSpeciesFileResult(fileValue);



                            }// for (int index = 0; index < ucnDataResult.Count ; index++)  结束

                        }


                    }

                    #endregion


                    this._mt3dOutputFileResult.AddSpeciesResult(mt3dSpeciesResult);

                }

            }
            catch
            {

                this._mt3dOutputFileResult = new MT3DOutputResult(speciesNum);
            }


            #endregion


        }





     


        /// <summary>
        /// 旧的使用dos程序postmt3d.exe生成的 txt 文件的读取方法  暂时不使用  被上面的直接读取二进制文件的方案代替
        /// </summary>
        /// <param name="path"></param>
        private void ReadMT3DTxtFiles(string path)
        {


            #region  旧的使用dos程序postmt3d.exe生成的 txt 文件的读取方法  暂时不使用  被上面的直接读取二进制文件的方案代替


            ////首先计算所有的污染的个数
            //int speciesNum = this.BasicTransport.SpeciesCollecion.SpeciesCount;

            //try
            //{


            //    //创建结果文件的数据存储对象
            //    this._mt3dOutputFileResult = new MT3DOutputResult(speciesNum);


            //    //然后计算每个污染物输出的文件的个数

            //    int fileNum = 0;
            //    List<string> fileName = new List<string>();
            //    System.IO.DirectoryInfo di = null;


            //    for (int i = 0; i < this.BasicTransport.SpeciesCollecion.Species.Count; i++)
            //    {
            //        //遍历污染物信息集合


            //        fileNum = 0;
            //        fileName.Clear();

            //        string outputFilePath = path + FileNameConfigHelper.GetMT3DResultDirectoryName(i);


            //        di = new System.IO.DirectoryInfo(outputFilePath);

            //        foreach (var item in di.GetFiles())
            //        {
            //            if (System.IO.Path.GetExtension(item.Name).ToLower() == ".txt")
            //            {
            //                fileNum = fileNum + 1;
            //                //fileName.Add(item.Name);
            //            }
            //        }
            //        for (int num = 0; num < fileNum; num++)
            //        {
            //            string name = (num + 1).ToString() + ".txt";
            //            fileName.Add(name);

            //        }

            //        MT3DSpeciesResult mt3dSpeciesResult = new MT3DSpeciesResult();

            //        //mt3dSpeciesResult.SpecieID = "";
            //        //mt3dSpeciesResult.SpecieName = "";
            //        mt3dSpeciesResult.SpecieName = this.BasicTransport.SpeciesCollecion.Species[i].Name;
            //        mt3dSpeciesResult.OutputFileNum = fileNum;

            //        //遍历该污染物生成的所有文件 读取文件内容

            //        #region

            //        if (fileName.Count > 0 && fileName.Count == fileNum)
            //        {
            //            for (int index = 0; index < fileName.Count; index++)
            //            {

            //                OutputFileData fileValue = new OutputFileData();


            //                string filePath = outputFilePath + "\\" + fileName[index];


            //                MT3DResultDataSetReader mt3dDataReader;

            //                if (this._mfData != null)
            //                {
            //                    mt3dDataReader = new MT3DResultDataSetReader(filePath, this._mfData.GridData.WaterGrid.GetIBounds());
            //                }
            //                else
            //                {
            //                    mt3dDataReader = new MT3DResultDataSetReader(filePath, null);
            //                }

            //                //MT3DResultDataSetReader mt3dDataReader = new MT3DResultDataSetReader(filePath, this._mfData.GridData.WaterGrid.GetIBounds());

            //                DataSet dataResult = mt3dDataReader.ReadData(0);//mt3d的文件中只对应一个网格的数据



            //                fileValue.FileLabel = fileName[index];

            //                fileValue.StressStep = mt3dDataReader.StressStep;
            //                fileValue.TimeStep = mt3dDataReader.TimeStep;
            //                fileValue.TransStep = mt3dDataReader.TransStep;
            //                fileValue.Time = mt3dDataReader.Time;
            //                fileValue.Conc = mt3dDataReader.Conc;
            //                fileValue.Col = mt3dDataReader.Col;
            //                fileValue.Row = mt3dDataReader.Row;
            //                fileValue.Layer = mt3dDataReader.Layer;


            //                fileValue.CellCenterGridValue = (CellCenterDataSet3d)dataResult;
            //                //fileValue.CellCenterGridValue.Label = mt3dDataReader.StressStep+"_"+mt3dDataReader.TimeStep+"_"+mt3dDataReader.TransStep;
            //                fileValue.CellCenterGridValue.Label = mt3dDataReader.StressStep + "_" + mt3dDataReader.TimeStep + "_" + mt3dDataReader.TransStep + "_" + mt3dDataReader.Time.ToString();


            //                mt3dSpeciesResult.AddSpeciesFileResult(fileValue);


            //            }

            //        }

            //        #endregion


            //        this._mt3dOutputFileResult.AddSpeciesResult(mt3dSpeciesResult);

            //    }




            //    //此部分还需要修改，暂时读取第一个文件

            //    //伪代码

            //    //string filePath = path + FileNameConfigHelper .GetMT3DResultDirectoryName (0)+"\\1.txt";//纠结的名字

            //    //MT3DResultDataSetReader mt3dDataReader = new MT3DResultDataSetReader(filePath);

            //    //DataSet dataResult=   mt3dDataReader.ReadData(0);//mt3d的文件中只对应一个网格的数据

            //    //this._mt3dDataResult = (CellCenterDataSet3d )dataResult;

            //}
            //catch
            //{
            //    //System.Windows.Forms.MessageBox.Show("");
            //    //this._mt3dDataResult = null;

            //    //this._mt3dOutputFileResult = null;
            //    this._mt3dOutputFileResult = new MT3DOutputResult(speciesNum);
            //}



            #endregion
        
        
        }





        #endregion



        #region 反序体制

        [OnDeserialized]
        public void OnDeserialized(StreamingContext context)
        {


            this.ReserveInnerEvents();


        }

        [OnSerializing]
        public void OnSerializing(StreamingContext context)
        {




        }

        #endregion


    }
}
